package main

import (
	"fmt"
)

// 结构体
type User1 struct {
	Name  string
	Email string
}

// 方法
func (u User1) Notify() {
	fmt.Printf("%v : %v \n", u.Name, u.Email)
}

type T struct {
	i int
}

type S struct {
	T
}

func (t T) test() {
	fmt.Println("类型 T 方法集包含全部 receiver T 方法。")
}

func (t *T) testP1() {
	fmt.Println("类型 *T 方法集包含全部 receiver *T 方法。")
}

func (t T) testT() {
	fmt.Println("如类型 S 包含匿名字段 T，则 S 和 *S 方法集包含 T 方法。")
}

func (t *T) testP() {
	fmt.Println("如类型 S 包含匿名字段 *T，则 S 和 *S 方法集包含 *T 方法")
}

type User struct {
	id   int
	name string
}

func (self *User) Test() {
	fmt.Printf("%p, %v\n", self, self)
}

func (self User) Test2() {
    fmt.Println(self)
}

func main() {
	// 值类型调用方法
	u1 := User1{"golang", "golang@golang.com"}
	u1.Notify()
	// 指针类型调用方法
	u2 := User1{"go", "go@go.com"}
	u3 := &u2
	u3.Notify()

	s1 := S{T{1}}
	s2 := &s1
	fmt.Printf("s1 is : %v\n", s1)
	s1.testT()
	s1.testP()
	fmt.Printf("s2 is : %v\n", s2)
	s2.testT()
	s2.testP()

	u := User{1, "Tom"}
	u.Test()

	mValue := u.Test
	mValue() // 隐式传递 receiver

	mExpression := (*User).Test
	mExpression(&u) // 显式传递 receiver

	u4 := User{1, "Tom"}
    mValue4 := u4.Test2 // 立即复制 receiver，因为不是指针类型，不受后续修改影响。

    u4.id, u4.name = 2, "Jack"
    u4.Test2()

    mValue4()
}
